home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Skinny3DSample / Skinny3DSources ƒ / 3DAppSpecific.c next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  26.3 KB  |  1,030 lines  |  [TEXT/MPS ]

  1. #include "Printing.h"
  2. #include "Windows.h"
  3. #include "Fonts.h"
  4. #include "Desk.h"
  5. #include "ToolUtils.h"
  6. #include "TextUtils.h"
  7. #include "LowMem.h"
  8. #include "SegLoad.h"
  9.  
  10.  
  11. #include    "3DAppSpecific.h"
  12.     // #include <QD3DHeaders.h>
  13. #include     "SkinnyMain.h"
  14. #include     "ValueControls.h"
  15.  
  16. #include     "BoxModel.h"
  17. #include    "Cameras.h"
  18. #include     "Lights.h"
  19.  
  20. /*
  21. prototypes of QD3DFunctions called from the application (in "3DAppSpecific.h"):
  22.  
  23. OSErr    InitializeApplication(void);
  24. void    Cleanup(void);
  25. Boolean PreflightNew(void); // return TRUE if "New" will work
  26. void     DoNew(void);
  27. void     DoOpen(void);
  28. void     DoClose(void); // FrontWindow() only
  29. void     DoSave(void);
  30. void     DoSaveAs(void);
  31. void     DoPrint(void);
  32. void     DoClickInContent(EventRecord *evt, WindowPtr theWindow);
  33. void     ActivateWindow(WindowPtr newFrontWindow, Boolean active);
  34.  
  35. void    DoAppSpecificMenu(long menuNumber, long itemNumber);
  36. void     UpdateAppMenus(void);
  37.  
  38. void    DrawAppSpecificContent(WindowPtr theWindow);
  39.  
  40. */
  41. enum { windowID = 128 }; // resource ID
  42.  
  43. #define kWidth        600
  44. #define kHeight        400
  45. #define kCntrlWdth    200
  46.  
  47. typedef enum DirectionType {
  48.     none, left, right, up, down, reset
  49. } DirectionType;
  50.  
  51. // data structure tied to a window (handle into wRefCon)
  52. struct WindowInfo {
  53.     TQ3ViewObject        view;
  54.     TQ3GroupObject        model;
  55.     TQ3TransformObject    rotation;
  56.     TQ3StyleObject        interpolation;
  57.     TQ3StyleObject        backfacing;
  58.     TQ3StyleObject        fillstyle;
  59.     TQ3ShaderObject         shader;
  60.     VccPtr                vcc;
  61. };
  62. typedef struct WindowInfo WindowInfo, **WinfoH;
  63.  
  64.  
  65. // local prototypes
  66. void AddHierarchMenu(long parentMenuID, long item, long subMenuID);
  67.  
  68. static    WinfoH     Make3Dinfo(WindowPtr theWindow);
  69. static    void    Dispose3Dinfo(WinfoH wInfoH);
  70.  
  71. static    void    Draw3DPart(WinfoH wInfo);
  72. static     void    DrawDirections(void);
  73. static     void    DrawTriangle(Point p, DirectionType e);
  74. static    void    DrawControlPart(WinfoH wInfo);
  75. static    Boolean            ControlClick(Point pt, WindowPtr theWindow);
  76. static    DirectionType     RotationClick(Point pt, WindowPtr theWindow);
  77.  
  78. static    TQ3DrawContextObject    MakeDrawContext(WindowPtr theWindow);
  79.  
  80. static void SetRotation(WinfoH wInfo, DirectionType direction);
  81.  
  82. static     void     ChooseDebug(long item);
  83.  
  84. static    void    ChooseRenderer    (TQ3ViewObject view, long item);
  85.  
  86. static    void    ChooseBackfacing    (WinfoH wInfo, long item);
  87. static    void    ChooseInterpolation    (WinfoH wInfo, long item);
  88. static    void    ChooseFillStyle        (WinfoH wInfo, long item);
  89.  
  90. static    void    MakeGeometry        (WinfoH wInfo, long selector);
  91. static    void    UpdateGeometry        (WinfoH wInfo);
  92. static    void    MakeDataControl        (WinfoH wInfo);
  93. static    void    MakeNewCamera        (WinfoH wInfo, long selector);
  94. static    void    MakeCameraControl    (WinfoH wInfo);
  95. static    void    MakeLightControl    (WinfoH wInfo, long selector);
  96.  
  97. static     Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo);
  98. void     CheckMenuItem(short menuID, short checkItem);
  99.  
  100. static     Rect    gWindowRect;
  101. static     Rect    g3DViewRect;
  102. Rect    gContrlRect; // needed to make VCC
  103.  
  104. static long curGeometry;
  105. static long curCamera;
  106. static long curLight;
  107. static long curRenderer;
  108. static long curBackfacing;
  109. static long curInterpol;
  110. static long curFillStyle;
  111.  
  112.  
  113. extern    THPrint        gPrintH;
  114. extern     CursHandle    gWatchCursor;
  115.  
  116.  
  117. //---------------------------------
  118. OSErr    InitializeApplication(void)
  119. {
  120.     MenuHandle    mh;
  121.     Handle         menuBar = GetNewMBar(128);
  122.     TQ3Status    status;
  123.     
  124.     if (!menuBar) {
  125.         return -30000;       
  126.     }
  127.     SetMenuBar(menuBar);
  128.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  129.     DrawMenuBar();
  130.     DisposeHandle(menuBar);
  131.     
  132.     AddHierarchMenu(mControl, iCamera,         mCameras);
  133.     AddHierarchMenu(mControl, iLight,         mLight);
  134.     AddHierarchMenu(mControl, iRenderer,     mRenderer);
  135.     
  136.     AddHierarchMenu(mStyle,   iBackfacing,    mBackfacing);
  137.     AddHierarchMenu(mStyle,   iInterpol,     mInterpolation);
  138.     AddHierarchMenu(mStyle,   iFillStyle,    mFillStyle);
  139.     
  140.     gPrintH = (THPrint)NewHandle(sizeof(TPrint));
  141.     if (gPrintH == nil)
  142.         return -30001;       
  143.     
  144.     status = Q3Initialize();
  145.     if ( status == kQ3Failure )
  146.         return ( -30002 );
  147.  
  148.     SetRect(&gWindowRect, 0, 0, kWidth, kHeight);
  149.     SetRect(&g3DViewRect, 0, 0, kWidth - kCntrlWdth, kHeight);
  150.     SetRect(&gContrlRect, kWidth - kCntrlWdth, 0, kWidth, kHeight);
  151.     InsetRect(&gContrlRect, 1, 1);
  152.  
  153.     return ( noErr );
  154. }
  155.  
  156. //---------------------------------------------------------------
  157. void AddHierarchMenu(long parentMenuID, long item, long subMenuID)
  158. {
  159.     MenuHandle    mh;
  160.     
  161.     mh = GetMenu(subMenuID);
  162.     InsertMenu(mh, -1);
  163.     mh = GetMenuHandle(parentMenuID);
  164.     SetItemCmd(mh, item, 0x1B);
  165.     SetItemMark(mh, item, (char)subMenuID);
  166. }
  167.  
  168.  
  169. //------------------------
  170. void    Cleanup(void)
  171. //------------------------
  172. {
  173.     TQ3Status status = Q3Exit();
  174.     // don't worry - the application heap disappears anyway,
  175.     // and we can't do anything about any failure of Q3Exit().
  176. }
  177.  
  178. //------------------------------------
  179. Boolean PreflightNew(void)
  180. {
  181.     long maxm, grow;
  182.     
  183.     maxm = MaxMem(&grow);
  184.     return (maxm > 1000000); // that's what our new QD3D window roughly needs!
  185. }
  186.  
  187. //------------------------------------
  188. void DoNew(void)
  189. {
  190.     WindowPtr    myWindow;
  191.     WinfoH        intoRefCon;
  192.     
  193.     myWindow = GetNewCWindow(windowID, nil, (WindowPtr)(-1));
  194.     if ( myWindow == nil ) {
  195.         ErrMsg("\pGetNewCWindow failed.");
  196.         return;
  197.     }
  198.     SizeWindow(myWindow, kWidth, kHeight, false);
  199.     ShowWindow(myWindow);
  200.     SetPort(myWindow);
  201.     intoRefCon = Make3Dinfo(myWindow);
  202.     if (intoRefCon != nil) {
  203.         SetWRefCon(myWindow, (long)intoRefCon );
  204.         DoAppSpecificMenu(mGeometry, iBox);
  205.     }
  206.     else {
  207.         ErrMsg("\pMake3Dinfo failed");
  208.         DisposeWindow(myWindow);
  209.     }
  210. }
  211.  
  212.  
  213. //------------------------------------
  214. void DoOpen(void)
  215. {
  216. }
  217.  
  218. //------------------------------------
  219. void DoClose(void)
  220. {
  221.     WindowPtr    theWindow;
  222.     WinfoH        theWinfo;
  223.     
  224.     if (GoodFrontWindow(&theWindow, &theWinfo))
  225.         Dispose3Dinfo(theWinfo);
  226.     CloseWindow(theWindow);
  227. }
  228.  
  229. //------------------------------------
  230. void DoSave(void)
  231. {
  232. }
  233.  
  234. //------------------------------------
  235. void DoSaveAs(void)
  236. {
  237. }
  238.  
  239. //------------------------------------
  240. void DoPrint( void )
  241. {
  242.     SysBeep(50);
  243. }
  244.  
  245. //----------------------------------------------------------------------
  246. void DoClickInContent(EventRecord *evt, WindowPtr theWindow)
  247. {
  248.     WinfoH            wInfo;
  249.     ControlHandle    ctlh;
  250.     Point            pt;
  251.     Rect            frame;
  252.     DirectionType    direction;
  253.     int                part;
  254.     
  255.     wInfo = (WinfoH)GetWRefCon(theWindow);
  256.     if (wInfo == nil) return;
  257.  
  258.     pt = evt->where;
  259.     GlobalToLocal(&pt);
  260.     if ((part = FindControl(pt, theWindow, &ctlh)) != kControlNoPart) {
  261.         /* TrackControl Goes Here */
  262.     }
  263.  
  264.     if (ControlClick(pt, theWindow)) { // our special ValueControl panel
  265.         InvalRect(&g3DViewRect);
  266.         return;
  267.     }
  268.     
  269.     if ((direction = RotationClick(pt, theWindow)) != none) {
  270.         SetRotation(wInfo, direction);
  271.         InvalRect(&g3DViewRect);
  272.     }
  273. }
  274.  
  275.  
  276. //------------------------------------
  277. static void SetRotation(WinfoH wInfo, DirectionType direction)
  278. {
  279.     TQ3Status            status;
  280.     TQ3BoundingBox        bBox;
  281.     TQ3Point3D            center, tmpPt;
  282.     TQ3Axis                axis;
  283.     float                angle;
  284.     TQ3Matrix4x4            previousMatrix, matrix, newMatrix, *tmp;
  285.     TQ3TransformObject     transform;
  286.     TQ3RotateAboutPointTransformData    tData;
  287.  
  288.     TQ3GroupObject        group;
  289.     TQ3GroupPosition        position;
  290.     TQ3ObjectType        type;
  291.     TQ3Object            theObj;
  292.     TQ3BoxData            boxData;
  293.     
  294.     if (direction == reset) {
  295.         Q3Matrix4x4_SetIdentity(&matrix);
  296.         status = Q3MatrixTransform_Set((**wInfo).rotation, &matrix);
  297.         return;
  298.     }
  299.     
  300. //    Q3View_StartBounds((**wInfo).view);
  301. //    status = Q3DisplayGroup_BoundingBox((**wInfo).model, 
  302. //                                        &bBox, 
  303. //                                         kQ3ComputeBoundsApproximate,
  304. //                                         (**wInfo).view);
  305. //    Q3View_EndBounds((**wInfo).view);
  306.     
  307.     // Cannot link with the above, for some temporary reason.
  308.     // Temporary workaround:
  309.     group = (**wInfo).model;
  310.     type = kQ3ShapeTypeGeometry;
  311.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  312.     if (status == kQ3Failure)
  313.         return;
  314.         
  315.     status = Q3Group_GetPositionObject ( group, position, &theObj);
  316.     type = Q3Geometry_GetType ( theObj );
  317.     switch (type) {
  318.         case kQ3GeometryTypeBox: 
  319.                 status = Q3Box_GetData( theObj, &boxData );
  320.                 bBox.min = boxData.origin;
  321.                 Q3Point3D_Vector3D_Add(&bBox.min, &boxData.orientation, &tmpPt);
  322.                 Q3Point3D_Vector3D_Add(&tmpPt,    &boxData.majorAxis, &tmpPt);
  323.                 Q3Point3D_Vector3D_Add(&tmpPt,       &boxData.minorAxis, &bBox.max);
  324.             break;
  325.             // add here the cases of other geometries, if required
  326.         default:
  327.             Q3Point3D_Set(&bBox.min, -1.0, -1.0, -1.0);
  328.             Q3Point3D_Set(&bBox.max, 1.0, 1.0, 1.0);
  329.             return;
  330.     }
  331.  
  332.     Q3Point3D_RRatio(&bBox.min, &bBox.max, 1.0, 1.0, ¢er); // mid-point
  333.     
  334.     status = Q3MatrixTransform_Get((**wInfo).rotation, &previousMatrix);
  335.     
  336.     if ((direction == up) || (direction == down))
  337.         axis = kQ3AxisX;
  338.     else
  339.         axis = kQ3AxisY;
  340.     if ((direction == right) || (direction == down))
  341.         angle = 0.1;
  342.     else
  343.         angle = -0.1;
  344.         
  345.     tData.axis = axis;
  346.     tData.radians = angle;
  347.     tData.about = center;
  348.     transform = Q3RotateAboutPointTransform_New(&tData);
  349.     if (transform == NULL)
  350.         return;
  351.     tmp = Q3Transform_GetMatrix(transform, &matrix);
  352.     
  353.     Q3Matrix4x4_Multiply(&previousMatrix, &matrix, &newMatrix);
  354.     status = Q3MatrixTransform_Set((**wInfo).rotation, &newMatrix);
  355.  
  356.  
  357. //------------------------------------
  358. void     ActivateWindow(WindowPtr newFrontWindow, Boolean active)
  359. {
  360.     if (active)
  361.         ;// This window is now active.  Controls should be enabled, etc.
  362.     else
  363.         ;
  364.     //    do anyting necessary to deactivate your windows here.
  365.     //    controls should be dimmed, etc.
  366. }
  367.  
  368. //------------------------------------
  369. void    DoAppSpecificMenu(long menuNumber, long item)
  370. {
  371.     WindowPtr    theWindow;
  372.     WinfoH        wInfo;
  373.     
  374.     if (menuNumber == mDebug) {
  375.         ChooseDebug(item); return;
  376.     }
  377.     
  378.     if (!GoodFrontWindow(&theWindow, &wInfo)) {
  379. //        ErrMsg("\pBad FrontWindow");
  380.         return;
  381.     }
  382.     
  383.     switch (menuNumber) {
  384.         case mGeometry: MakeGeometry(wInfo, item);
  385.                         MakeDataControl(wInfo);
  386.                         curGeometry = item;
  387.                         break;
  388.         case mControl:     if (item == iData)
  389.                         MakeDataControl(wInfo);
  390.                         break;
  391.                 
  392.         case mCameras:     if (item != curCamera) {
  393.                             MakeNewCamera(wInfo, item);
  394.                             curCamera = item;
  395.                         }
  396.                         MakeCameraControl(wInfo);
  397.                         break;
  398.         case mLight:     MakeLightControl(wInfo, item);
  399.                         curLight = item;
  400.                         break;
  401.         case mRenderer: ChooseRenderer((**wInfo).view, item);
  402.                         break;
  403.  
  404.         case mBackfacing:
  405.                         ChooseBackfacing(wInfo, item);
  406.                         curBackfacing = item;
  407.                         break;
  408.         case mInterpolation:
  409.                         ChooseInterpolation(wInfo, item);
  410.                         curInterpol = item;
  411.                         break;
  412.         case mFillStyle:
  413.                         ChooseFillStyle(wInfo, item);
  414.                         curFillStyle = item;
  415.                         break;
  416.         
  417.         default:
  418.             break;
  419.     }
  420.     InvalRect(&theWindow->portRect);
  421. }
  422.  
  423.  
  424. //------------------------------------
  425. void UpdateAppMenus(void)
  426. {
  427.     long free, maxm, grow;
  428.     Str255 freeItem = "\pFreeMem = ";
  429.     Str255 maxmItem = "\pMaxMem  = ";
  430.     Str255 s;
  431.     WindowPtr    theWindow;
  432.     WinfoH        wInfo;
  433.     MenuHandle    menu = GetMenuHandle(mDebug);
  434.     
  435.     free = FreeMem();
  436.     NumToString(free, s);
  437.     pcat(freeItem, s);
  438.     SetMenuItemText(menu, iFreeMem, freeItem);
  439.  
  440.     maxm = MaxMem(&grow);
  441.     NumToString(maxm, s);
  442.     pcat(maxmItem, s);
  443.     SetMenuItemText(menu, iMaxMem, maxmItem);
  444.     
  445.     CheckMenuItem(mGeometry, curGeometry);
  446.     CheckMenuItem(mCameras, curCamera);
  447.     CheckMenuItem(mLight, curLight);
  448.     CheckMenuItem(mRenderer, curRenderer);
  449.     CheckMenuItem(mBackfacing, curBackfacing);
  450.     CheckMenuItem(mInterpolation, curInterpol);
  451.     CheckMenuItem(mFillStyle, curFillStyle);
  452.     
  453.     if (!GoodFrontWindow(&theWindow, &wInfo)) {
  454.         DisableItem(GetMenuHandle(mGeometry), 0);
  455.         DisableItem(GetMenuHandle(mControl), 0);
  456.         DisableItem(GetMenuHandle(mStyle), 0);
  457.     }
  458.     else {
  459.         EnableItem(GetMenuHandle(mGeometry), 0);
  460.         EnableItem(GetMenuHandle(mControl), 0);
  461.         EnableItem(GetMenuHandle(mStyle), 0);
  462.     }
  463.     DrawMenuBar();
  464. }
  465.  
  466.  
  467. void CheckMenuItem(short menuID, short checkItem)
  468. {
  469.     MenuHandle    menu = GetMenuHandle(menuID);
  470.     short         n = CountMItems(menu);
  471.     short        i;
  472.     
  473.     for (i = 1; i <= n; i++)
  474.         CheckItem(menu, i, (i == checkItem));
  475. }
  476.  
  477.  
  478. //------------------------------------
  479. static    void    ChooseRenderer(TQ3ViewObject view, long item)
  480. {
  481.     TQ3Status            status;
  482.     TQ3ObjectType        rType;
  483.     TQ3RendererObject    renderer;
  484.     
  485.     switch (item) {
  486.         case iWireFrame: rType = kQ3RendererTypeWireFrame;     break;
  487.         case iZBuffer:     rType = kQ3RendererTypeInteractive;     break;
  488.     }
  489.     
  490. //    status = Q3View_SetRendererByType(view, rType);
  491. //  alternatively:
  492.     renderer = Q3Renderer_NewFromType(rType);
  493.     if (renderer == nil)
  494.         return;
  495.     status = Q3View_SetRenderer(view, renderer);
  496.     if (status == kQ3Failure )
  497.         return;
  498.         
  499.     Q3Object_Dispose(renderer) ;
  500.  
  501.     curRenderer = item;
  502. }
  503.  
  504. //------------------------------------
  505. static    void    ChooseBackfacing(WinfoH    wInfo, long item)
  506. {
  507.     TQ3Status            status;
  508.     TQ3BackfacingStyle     bfStyle;
  509.     
  510.     switch (item) {
  511.         case iBoth:     bfStyle = kQ3BackfacingStyleBoth;             break;
  512.         case iRemove:    bfStyle = kQ3BackfacingStyleRemove;     break;
  513.           case iFlip:     bfStyle = kQ3BackfacingStyleFlip;         break;
  514.     }
  515.     if ((**wInfo).backfacing != nil)
  516.         status = Q3Object_Dispose((**wInfo).backfacing);
  517.     (**wInfo).backfacing = Q3BackfacingStyle_New(bfStyle);
  518. }
  519.  
  520. //------------------------------------
  521. static    void    ChooseInterpolation(WinfoH    wInfo, long item)
  522. {
  523.     TQ3Status                status;
  524.     TQ3InterpolationStyle    ipStyle;
  525.     
  526.     switch (item) {
  527.         case iNone:     ipStyle = kQ3InterpolationStyleNone;     break;
  528.         case iVertex:    ipStyle = kQ3InterpolationStyleVertex;     break;
  529.           case iPixel:     ipStyle = kQ3InterpolationStylePixel;     break;
  530.     }
  531.     if ((**wInfo).interpolation != nil)
  532.         status = Q3Object_Dispose((**wInfo).interpolation);
  533.     (**wInfo).interpolation = Q3InterpolationStyle_New(ipStyle);
  534. }
  535.  
  536.  
  537. //------------------------------------
  538. static    void    ChooseFillStyle(WinfoH    wInfo, long item)
  539. {
  540.     TQ3Status            status;
  541.     TQ3FillStyle            flStyle;
  542.     
  543.     switch (item) {
  544.         case iFilled:     flStyle = kQ3FillStyleFilled;    break;
  545.         case iEdges:    flStyle = kQ3FillStyleEdges;    break;
  546.           case iPoints:     flStyle = kQ3FillStylePoints;    break;
  547.     }
  548.     if ((**wInfo).fillstyle != nil)
  549.         status = Q3Object_Dispose((**wInfo).fillstyle);
  550.     (**wInfo).fillstyle = Q3FillStyle_New(flStyle);
  551. }
  552.  
  553.  
  554. //------------------------------------
  555. static void ChooseDebug(long item)
  556. {    
  557. }
  558.  
  559. //////////////////////////////////////////////////////////
  560. //===========================================
  561. WinfoH Make3Dinfo(WindowPtr theWindow)
  562. {
  563.     WinfoH                wInfo;
  564.     TQ3DrawContextObject drawContext;
  565.     TQ3RendererObject    renderer;
  566.     TQ3GroupObject        lightGroup;
  567.     TQ3Matrix4x4            matrix;
  568.     TQ3Status            status;
  569.     
  570.     wInfo = (WinfoH) NewHandleClear(sizeof(WindowInfo));
  571.     if (wInfo == nil) {
  572.         ErrMsg("\pNewHandle(WindowInfo) failed");
  573.         return nil;
  574.     }
  575.     
  576.     (**wInfo).view = Q3View_New();    // Escher View
  577.     if ( (**wInfo).view == nil ) goto fail;
  578.  
  579.     // Set DrawContext, Camera, lightGroup and Renderer
  580.     drawContext = MakeDrawContext(theWindow);
  581.     if ( drawContext == nil ) goto fail;
  582.     status = Q3View_SetDrawContext((**wInfo).view, drawContext);
  583.     if ( status == kQ3Failure ) goto fail;
  584.     status = Q3Object_Dispose(drawContext); 
  585.  
  586.     MakeNewCamera(wInfo, iAspectRatio);
  587.  
  588.     lightGroup = MakeLights();
  589.     if ( lightGroup == nil ) goto fail;
  590.     status = Q3View_SetLightGroup((**wInfo).view, lightGroup);
  591.     if ( status == kQ3Failure ) goto fail;
  592.     // decrease reference count (was increased by Q3View_SetLightGroup
  593.     Q3Object_Dispose(lightGroup);
  594.     
  595.     curLight = 0; // selector for valuecontrol initially undefined
  596.     
  597.     ChooseRenderer((**wInfo).view, iWireFrame);
  598.  
  599.     (**wInfo).shader = Q3LambertIllumination_New() ;
  600.  
  601.     //    Create model to display.
  602.     (**wInfo).model = Q3OrderedDisplayGroup_New();
  603.     if ( (**wInfo).model == nil ) goto fail;
  604.  
  605.     // Set identity transform
  606.     Q3Matrix4x4_SetIdentity(&matrix);
  607.     (**wInfo).rotation = Q3MatrixTransform_New(&matrix);
  608.  
  609.     //    Configure the drawing styles.
  610.     ChooseInterpolation    (wInfo, iNone);        curInterpol     = iNone;
  611.     ChooseBackfacing    (wInfo, iBoth);        curBackfacing     = iBoth;
  612.     ChooseFillStyle        (wInfo, iFilled);    curFillStyle     = iFilled;
  613.  
  614.     return wInfo;
  615.     
  616. fail:
  617.     Dispose3Dinfo(wInfo);
  618.     return nil;
  619. }
  620.  
  621. // ---------------------------------------------------------------------
  622. void    Dispose3Dinfo(WinfoH wInfoH)
  623. {
  624.     TQ3Status    status;
  625.     
  626.     if (wInfoH == nil) return;
  627.     if ((**wInfoH).view != nil)
  628.         status = Q3Object_Dispose((**wInfoH).view);
  629.     if ((**wInfoH).model != nil) {
  630.         // need to dispose properly of everything ...
  631.         status = Q3Object_Dispose((**wInfoH).model);
  632.     }
  633.     if ((**wInfoH).interpolation != nil)
  634.         status = Q3Object_Dispose((**wInfoH).interpolation);
  635.     if ((**wInfoH).backfacing != nil)
  636.         status = Q3Object_Dispose((**wInfoH).backfacing);
  637.     if ((**wInfoH).fillstyle != nil)
  638.         status = Q3Object_Dispose((**wInfoH).fillstyle);
  639.     DisposeHandle((Handle) wInfoH);
  640. }
  641.  
  642.  
  643. // --------------------------------------------------------------------
  644. TQ3DrawContextObject MakeDrawContext(WindowPtr theWindow)
  645. {
  646.     TQ3DrawContextData        drawContextData;
  647.     TQ3MacDrawContextData    macDrawContextData;
  648.     TQ3ColorARGB            ClearColor;
  649.     
  650.     //    Set the background color.
  651.     ClearColor.a = 1.0; /* Solid alpha */
  652.     ClearColor.r = 1.0;
  653.     ClearColor.g = 1.0;
  654.     ClearColor.b = 1.0;
  655.     
  656.     //    Fill in draw context data.
  657.     drawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  658.     drawContextData.clearImageColor = ClearColor;
  659.     drawContextData.pane.min.x = (theWindow->portRect).left;
  660.     drawContextData.pane.max.x = (theWindow->portRect).right;
  661.     drawContextData.pane.min.y = (theWindow->portRect).top;
  662.     drawContextData.pane.max.y = (theWindow->portRect).bottom;
  663.     drawContextData.paneState = kQ3True;
  664.     drawContextData.maskState = kQ3False;
  665.     drawContextData.doubleBufferState = kQ3True;
  666.  
  667.     macDrawContextData.drawContextData = drawContextData;
  668.     macDrawContextData.window = (CWindowPtr) theWindow;
  669.     macDrawContextData.library = kQ3Mac2DLibraryQuickDraw;
  670.     macDrawContextData.viewPort = nil;
  671.     macDrawContextData.grafPort = (CGrafPtr) theWindow;
  672.  
  673.     //    Create draw context.
  674.     return  Q3MacDrawContext_New(&macDrawContextData);
  675.     
  676. }
  677.  
  678. //----------------------------------------------------------------------------------
  679. void    DrawAppSpecificContent(WindowPtr theWindow)
  680. {
  681.     WinfoH wInfo;
  682.     
  683.     wInfo = (WinfoH)GetWRefCon(theWindow);
  684.     if (wInfo == nil)
  685.         return;
  686.     Draw3DPart(wInfo);
  687.     DrawControlPart(wInfo);
  688. }
  689.  
  690. //----------------------------------------------------------------------------------
  691. static void Draw3DPart(WinfoH wInfo)
  692. {
  693.     TQ3Status                status;
  694.     //TQ3DrawContextObject        myDrawContext;
  695.     TQ3ViewStatus            myViewStatus;
  696.     WindowInfo                wI = **wInfo;
  697.     TQ3RendererObject        myRenderer ;
  698.     
  699.     status = Q3View_StartRendering(wI.view);
  700.     if ( status == kQ3Failure ) goto bail;
  701.     
  702.     if (curInterpol == iPixel)
  703.         SetCursor(*gWatchCursor);
  704.  
  705.     do {
  706.         if (curFillStyle == iFilled) {
  707.             status = Q3Shader_Submit(wI.shader, wI.view);
  708.             if ( status == kQ3Failure ) goto bail;
  709.         }
  710.         status = Q3Style_Submit(wI.interpolation, wI.view);
  711.         if ( status == kQ3Failure ) goto bail;
  712.         status = Q3Style_Submit(wI.backfacing, wI.view);
  713.         if ( status == kQ3Failure ) goto bail;
  714.         status = Q3Style_Submit(wI.fillstyle, wI.view);
  715.         if ( status == kQ3Failure ) goto bail;
  716.         status = Q3Transform_Submit( wI.rotation, wI.view);
  717.         if ( status == kQ3Failure ) goto bail;
  718.         status = Q3DisplayGroup_Submit(wI.model, wI.view);
  719.         if ( status == kQ3Failure ) goto bail;
  720.         myViewStatus = Q3View_EndRendering(wI.view);
  721.     } while ( myViewStatus == kQ3ViewStatusRetraverse );
  722.     
  723.     // get the renderer from the view
  724.     status = Q3View_GetRenderer( wI.view, &myRenderer ) ;
  725.     if ( status == kQ3Failure ) goto bail;
  726.             
  727.     // call sync 'cos we are going to draw over it.  This is needed since if we are running with
  728.     // hardware (which is asynchronous) then we need to ensure that the HW has finished drawing
  729.     // before drawing the controls.
  730.     Q3Renderer_Sync( myRenderer, wI.view ) ;
  731.     
  732.     status = Q3Object_Dispose(myRenderer); 
  733.     
  734.     DrawDirections();
  735.     
  736.     InitCursor();
  737.     return;
  738.  
  739. bail:
  740.     SysBeep(50);
  741. }
  742.  
  743. //------------------------------------
  744. static     void    DrawDirections(void)
  745. {
  746.     Point    p;
  747.     short     d = 4; // distance from border
  748.     
  749.     p.h = (g3DViewRect.right - g3DViewRect.left) / 2;
  750.     p.v = g3DViewRect.top + d;
  751.     DrawTriangle(p, up);
  752.     p.v = g3DViewRect.bottom - d;
  753.     DrawTriangle(p, down);
  754.     p.h = g3DViewRect.left + d; 
  755.     p.v = (g3DViewRect.bottom - g3DViewRect.top) / 2;
  756.     DrawTriangle(p, left);
  757.     p.h = g3DViewRect.right - d;
  758.     DrawTriangle(p, right);
  759.     MoveTo(g3DViewRect.right - 20, g3DViewRect.top + 14);
  760.     TextFont(geneva); TextSize(12); TextFace(0);
  761.     DrawString("\p(R)");
  762. }
  763.  
  764. //------------------------------------
  765. static     void    DrawTriangle(Point p, DirectionType e)
  766. {
  767. #define        k   10 
  768.  
  769.     short    x1, y1, x2, y2, x3, y3;
  770.     
  771.     switch (e) {
  772.     case up:    x1 = y1 = x3 = k; y3 = -k; x2 = - k - k; y2 = 0;    break;
  773.     case down:    x1 = y1 = x3 = -k; y3 = k; x2 = k + k; y2 = 0;        break;
  774.     case left:    x1 = y1 = y3 = k; x3 = -k; x2 = 0; y2 = - k - k;    break;
  775.     case right: x1 = y1 = y3 = -k; x3 = k; x2 = 0; y2 = k + k;        break;
  776.     }
  777.         
  778.     MoveTo(p.h, p.v);
  779.     Line(x1, y1); Line(x2, y2); Line(x3, y3);
  780. }
  781.  
  782. //------------------------------------
  783. static    void    DrawControlPart(WinfoH wInfo)
  784. {
  785.     EraseRect(&gContrlRect);
  786.     FrameRect(&gContrlRect);
  787.     if ((**wInfo).vcc != nil)
  788.         DrawVCluster((**wInfo).vcc);
  789. }
  790.  
  791.  
  792. //------------------------------------
  793. static Boolean    ControlClick(Point pt, WindowPtr theWindow)
  794. {
  795.     WinfoH        wInfo;
  796.     OSType        tag;
  797.     TQ3Status    status;
  798.     
  799.     wInfo = (WinfoH)GetWRefCon(theWindow);
  800.     if (wInfo == nil)
  801.         return false;
  802.  
  803.     if ( TakeHit(pt, (**wInfo).vcc) ) {
  804.         tag = GetIdTag((**wInfo).vcc);
  805.         switch (tag) {
  806.             case kQ3GeometryTypeBox:
  807.                     UpdateGeometry(wInfo);
  808.                 break;
  809.                 
  810.             case kQ3CameraTypeOrthographic:
  811.             case kQ3CameraTypeViewPlane:
  812.             case kQ3CameraTypeViewAngleAspect:
  813.                 {
  814.                     TQ3CameraObject    camera;
  815.                 
  816.                     status = Q3View_GetCamera((**wInfo).view, &camera);
  817.                     VCCtoCameraData((**wInfo).vcc, camera);
  818.                     status = Q3View_SetCamera((**wInfo).view, camera);
  819.                     status = Q3Object_Dispose(camera); 
  820.                 }
  821.                 break;
  822.  
  823.             case kQ3LightTypeAmbient:
  824.             case kQ3LightTypeDirectional:
  825.             case kQ3LightTypePoint:
  826.             case kQ3LightTypeSpot:
  827.                 {
  828.                     TQ3CameraObject    camera;
  829.                     TQ3GroupObject    lightGroup;
  830.  
  831.                     status = Q3View_GetLightGroup((**wInfo).view, &lightGroup);
  832.                     VCCtoLight((**wInfo).vcc, lightGroup);                
  833.                 }
  834.                 break;
  835.  
  836.         // add here other types of valueControls
  837.         }
  838.         return true;
  839.     }
  840.     else
  841.         return false;
  842. }
  843.  
  844.  
  845. //----------------------------------------------------------------------------------
  846. static    DirectionType  RotationClick(Point pt, WindowPtr theWindow)
  847. {
  848.     Rect    leftRect, rightRect, upRect, downRect, resetRect;
  849.     Rect    r = g3DViewRect;  // shorthand notation
  850.     short     h3 = (g3DViewRect.right - g3DViewRect.left) / 3;
  851.     short     v3 = (g3DViewRect.bottom - g3DViewRect.top) / 3;
  852.     
  853.     SetRect(&leftRect,     r.left,          r.top + v3,      r.left + h3,   r.bottom - v3);
  854.     SetRect(&rightRect, r.right - h3, r.top + v3,      r.right,         r.bottom - v3);
  855.     SetRect(&upRect,     r.left + h3,  r.top,          r.right - h3,  r.top + v3);
  856.     SetRect(&downRect,     r.left + h3,  r.bottom - v3, r.right - h3,  r.bottom);
  857.     SetRect(&resetRect, r.right - 32,  r.top, r.right,  r.top + 32);
  858.     if (PtInRect(pt, &leftRect))    return left;
  859.     if (PtInRect(pt, &rightRect))     return right;
  860.     if (PtInRect(pt, &upRect))        return up;
  861.     if (PtInRect(pt, &downRect))    return down;
  862.     if (PtInRect(pt, &resetRect))    return reset;
  863.     return none;
  864. }
  865.  
  866. //----------------------------------------------------------------------------------
  867. void    MakeGeometry(WinfoH wInfo, long selector)
  868. {
  869.     if ((**wInfo).model != NULL) {
  870.     // ••• need to release memory allocated in attributes!
  871.         Q3Group_EmptyObjects((**wInfo).model);
  872.         Q3Object_Dispose((**wInfo).model);
  873.     }
  874.     
  875.     switch (selector) {
  876.         case iBox:     (**wInfo).model = MakeBox();
  877.             break;
  878.         case iEllipsoid:// aGeometry = MakeEllipsoid();
  879.                     SysBeep(10);
  880.             break;
  881.         case iCylinder: // aGeometry = MakeCylinder();
  882.                     SysBeep(10);
  883.             break;
  884.         case iCone:     // aGeometry = MakeCone();
  885.                     SysBeep(10);
  886.             break;
  887.         case iTorus:     // aGeometry = MakeTorus();
  888.                     SysBeep(10);
  889.             break;
  890.  
  891.         default:
  892.             break;
  893.     }
  894. }
  895.  
  896.  
  897. //----------------------------------------------------------------------------------
  898. void    MakeDataControl(WinfoH wInfo)
  899. {
  900.     TQ3GroupObject        group;
  901.     TQ3GroupPosition        position;
  902.     TQ3ObjectType        type;
  903.     TQ3Status            status;
  904.     TQ3Object            theObj;
  905.  
  906.     if ((**wInfo).vcc != nil) {
  907.         DisposeVCluster((**wInfo).vcc);
  908.         (**wInfo).vcc = nil;
  909.     }
  910.     
  911.     group = (**wInfo).model;
  912.     type = kQ3ShapeTypeGeometry;
  913.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  914.     if (status == kQ3Failure)
  915.         return;
  916.         
  917.     status = Q3Group_GetPositionObject ( group, position, &theObj);
  918.     type = Q3Geometry_GetType ( theObj );
  919.     switch (type) {
  920.         case kQ3GeometryTypeBox: 
  921.             (**wInfo).vcc = BoxDataToVCC(theObj);
  922.             break;
  923.             // add here data of other geometries
  924.         default:
  925.             return;
  926.     }
  927. }
  928.  
  929.  
  930. //----------------------------------------------------------------------------------
  931. static void MakeNewCamera (WinfoH wInfo, long selector)
  932. {
  933.     TQ3CameraObject        camera;
  934.     TQ3Status            status;
  935.     
  936.     camera = MakeCamera(selector);
  937.     status = Q3View_SetCamera((**wInfo).view, camera);
  938.     if ( status != kQ3Success )
  939.         ErrMsg("\pSetCamera failed");
  940.     status = Q3Object_Dispose(camera); 
  941.     curCamera = selector;
  942. }
  943.  
  944.  
  945. //----------------------------------------------------------------------------------
  946. static void MakeCameraControl(WinfoH wInfo)
  947. {
  948.     TQ3CameraObject    camera;
  949.     TQ3Status        status;
  950.  
  951.     if ((**wInfo).vcc != nil) {
  952.         DisposeVCluster((**wInfo).vcc);
  953.         (**wInfo).vcc = nil;
  954.     }
  955.     status = Q3View_GetCamera((**wInfo).view, &camera);
  956.     if (status != kQ3Success)
  957.         return;
  958.     (**wInfo).vcc = CameraDataToVCC(camera);
  959.     status = Q3Object_Dispose(camera); 
  960. }
  961.  
  962.  
  963. //----------------------------------------------------------------------------------
  964. static void MakeLightControl (WinfoH wInfo, long selector)
  965. {
  966.     TQ3Status        status;
  967.     TQ3GroupObject    lightGroup;
  968.         
  969.     if ((**wInfo).vcc != nil) {
  970.         DisposeVCluster((**wInfo).vcc);
  971.         (**wInfo).vcc = nil;
  972.     }
  973.     status = Q3View_GetLightGroup((**wInfo).view, &lightGroup);
  974.     (**wInfo).vcc = LightToVCC(lightGroup, selector);
  975. }
  976.  
  977.  
  978. //----------------------------------------------------------------------------------
  979. static void    UpdateGeometry(WinfoH wInfo)
  980. {
  981.     TQ3GroupObject        group;
  982.     TQ3GroupPosition        position;
  983.     TQ3ObjectType        type;
  984.     TQ3Status            status;
  985.     TQ3Object            theObj;
  986.     
  987.     group = (**wInfo).model;
  988.     type = kQ3ShapeTypeGeometry;
  989.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  990.     if (status == kQ3Failure)
  991.         return;
  992.         
  993.     status = Q3Group_GetPositionObject( group, position, &theObj);
  994.     type = Q3Geometry_GetType( theObj );
  995.     switch (type) {
  996.         case kQ3GeometryTypeBox: {
  997.                 TQ3BoxData    boxData;
  998.                 status = Q3Box_GetData(theObj, &boxData);
  999.                 if (status == kQ3Failure)
  1000.                     return; 
  1001.                 VCCtoBoxData((**wInfo).vcc, &boxData);
  1002.                 status = Q3Box_SetData(theObj, &boxData);
  1003.             //    Q3Box_EmptyData(&boxData);
  1004.             }
  1005.             break;
  1006.             // add here data of other geometries
  1007.         default:
  1008.             return;
  1009.     }
  1010.     status = Q3Group_SetPositionObject( group, position, theObj);
  1011.     status = Q3Object_Dispose(theObj); 
  1012. }
  1013.  
  1014.  
  1015.  
  1016. //----------------------------------------------------------------------------------
  1017. static Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo)
  1018. {
  1019.     WindowPtr    w;
  1020.     Boolean        isGood = true;
  1021.     
  1022.     w = FrontWindow();
  1023.     if (w == nil) // menu item should be disabled!
  1024.         isGood = false;
  1025.     if ( (*(WindowRecord *)w).windowKind != userKind )
  1026.         isGood = false;
  1027.     *theWindow = w;
  1028.     *wInfo = (WinfoH)GetWRefCon(w);
  1029.